library(shiny)
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ───────────────────────────────────────────────────── tidyverse 1.3.2 ──✔ ggplot2 3.3.6 ✔ purrr 0.3.4
✔ tibble 3.1.8 ✔ dplyr 1.0.9
✔ tidyr 1.2.0 ✔ stringr 1.4.0
✔ readr 2.1.2 ✔ forcats 0.5.1── Conflicts ──────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
obps_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-GMKN-2007-10-08-09_obps.csv")
Rows: 394482 Columns: 12── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): SECCODE, BUYSELL
dbl (9): NO, TIME, ORDERNO, ACTION, PRICE, VOLUME, TRADENO, TRADEPRICE, OBPLOTNO
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# obps_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-2007-10-08_obps.csv")
# obps_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/s1_s2_2007_obps.csv")
obps_df <- obps_df %>%
mutate(TIME_S = TIME/1000)
obps_df
order_atts_cumsums_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-GMKN-2007-10-08-09_order_atts_cumsums.csv")
Rows: 394482 Columns: 32── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): ATT, SECCODE
dbl (28): VAL, NO, OBPLOTNO, SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE, CBOV...
dttm (1): DATETIMEMLLS
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# order_atts_cumsums_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-2007-10-08_order_atts_cumsums.csv")
# order_atts_cumsums_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/s1_s2_2007_order_atts_cumsums.csv")
order_atts_cumsums_df
obp_cum_atts_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-GMKN-2007-10-08-09_obp_cum_atts.csv")
Rows: 75021 Columns: 6── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): SECCODE, BUYSELLOBP, TRADESNOTRADES
dbl (2): OBPLOTNO, TRADEVOL
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# obp_cum_atts_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-2007-10-08_obp_cum_atts.csv")
# obp_cum_atts_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/s1_s2_2007_obp_cum_atts.csv")
obp_cum_atts_df
order_atts_cumsums_enhanced_df <- left_join(order_atts_cumsums_df,
obps_df %>% select(-OBPLOTNO, -SECCODE),
by = c("NO", "DATE")) %>%
select(NO, SECCODE, DATETIMEMLLS, PRICE, TRADEPRICE, VOLUME,
DATE, TIME_S, OBPLOTNO, ATT, VAL,
SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE,
CBOVOLtdcs, CSOVOLtdcs, BOVOLtdcs, SOVOLtdcs, BTVOLtdcs, STVOLtdcs,
CBOVOLobpcs, CSOVOLobpcs, BOVOLobpcs, SOVOLobpcs, BTVOLobpcs, STVOLobpcs,
sobp, bobp, max_sobp_bobp, minus_max_sobp_bobp, stday, btday, max_std_btd,
minus_max_std_btd)
order_atts_cumsums_enhanced_df
obp_minmax_tradeprice <- function(att, tradeprice, minmax) {
at_df <- tibble(att = att,
tradeprice = tradeprice)
if (length(at_df %>%
filter(att == "BTVOL" | att == "STVOL") %>%
.$tradeprice)) {
if (minmax == "min") {
min(at_df %>%
filter(att == "BTVOL" | att == "STVOL") %>%
.$tradeprice %>%
cummin())
} else if (minmax == "max") {
max(at_df %>%
filter(att == "BTVOL" | att == "STVOL") %>%
.$tradeprice %>%
cummax())
} else quit()
} else {
NA
}
}
obp_minmax_atts_df <- order_atts_cumsums_enhanced_df %>%
select(NO, SECCODE, DATE, OBPLOTNO, ATT,
DATETIMEMLLS, PRICE, TRADEPRICE) %>%
group_by(SECCODE, DATE, OBPLOTNO) %>%
summarise(OBPBEGIN = min(DATETIMEMLLS), OBPEND = max(DATETIMEMLLS),
OBPBEGINNO = min(NO), OBPENDNO = max(NO),
OBPMINPRICE = min(PRICE), OBPMAXPRICE = max(PRICE))
`summarise()` has grouped output by 'SECCODE', 'DATE'. You can override using the `.groups` argument.
obp_minmax_atts_df
obp_cum_minmax_atts_df <- left_join(obp_cum_atts_df,
obp_minmax_atts_df %>% select(SECCODE,
DATE,
OBPLOTNO,
OBPBEGIN,
OBPBEGINNO,
OBPENDNO,
OBPEND,
OBPMINPRICE,
OBPMAXPRICE),
by = c("SECCODE", "DATE", "OBPLOTNO")) %>%
select(SECCODE, DATE, OBPLOTNO, TRADEVOL, BUYSELLOBP,
OBPBEGIN, OBPEND, OBPBEGINNO, OBPENDNO, OBPMINPRICE, OBPMAXPRICE,
TRADESNOTRADES) #, BUYSELLYIELD, OBPTDVOLRATIO, MINMAXRATIO)
obp_cum_minmax_atts_df
obp_cum_atts_enh_df <- inner_join(obp_cum_minmax_atts_df,
order_atts_cumsums_enhanced_df %>% select(SECCODE,
DATE,
OBPLOTNO,
BPROFIT,
SPROFIT),
by = c("SECCODE", "DATE", "OBPLOTNO")) %>%
select(SECCODE, DATE, OBPLOTNO, TRADEVOL, BUYSELLOBP,
BPROFIT, SPROFIT,
OBPBEGIN, OBPEND, OBPBEGINNO, OBPENDNO, OBPMINPRICE, OBPMAXPRICE,
TRADESNOTRADES) %>% #, BUYSELLYIELD, OBPTDVOLRATIO, MINMAXRATIO) %>%
rename("seccode" = "SECCODE",
"ddate" = "DATE",
"obplotno" = "OBPLOTNO",
"tradevol" = "TRADEVOL",
"buysellobp" = "BUYSELLOBP",
"bprofit" = "BPROFIT",
"sprofit" = "SPROFIT",
"obpbegin" = "OBPBEGIN",
"obpend" = "OBPEND",
"obpbeginno" = "OBPBEGINNO",
"obpendno" = "OBPENDNO",
"obpminprice" = "OBPMINPRICE",
"obpmaxprice" = "OBPMAXPRICE",
"bprofit" = "BPROFIT",
"sprofit" = "SPROFIT",
"tradesnotrades" = "TRADESNOTRADES") %>%
distinct()
# "buysellyield" = "BUYSELLYIELD",
# "obptdvolratio" = "OBPTDVOLRATIO",
# "minmaxratio" = "MINMAXRATIO")
obp_cum_atts_enh_df
td_vol_sum_df <- obp_cum_atts_enh_df %>%
group_by(seccode, ddate) %>%
summarise(tdvolsum = sum(tradevol))
`summarise()` has grouped output by 'seccode'. You can override using the `.groups` argument.
obp_cum_atts_enh_volarranged_df <- left_join(obp_cum_atts_enh_df,
td_vol_sum_df,
by = c("seccode", "ddate")) %>%
mutate(obpshareintd = tradevol / tdvolsum) %>%
select(-tdvolsum) %>%
arrange(seccode, ddate, desc(obpshareintd))
obp_cum_atts_enh_volarranged_df
options(digits.secs = 3)
obp_cum_atts_enh_volarranged_df %>%
write_csv("../order-book-plot-find/cum_errors/resources/for_web_app/obp_cum_atts_enh_df.csv",
na = "")
order_atts_cumsums_enh2_df <- order_atts_cumsums_enhanced_df %>%
mutate(pcolor = if_else(ATT == "BOVOL",
"aquamarine",
if_else(ATT == "SOVOL",
"coral",
"#004481")),
pshape = 4L,
psize = 0.5)
order_atts_cumsums_enh2_df
order_atts_cumsums_enh4_df <- order_atts_cumsums_enh2_df %>%
arrange(SECCODE, DATE, NO) %>%
rename("nno" = "NO",
"seccode" = "SECCODE",
"datetimemlls" = "DATETIMEMLLS",
"price" = "PRICE",
"tradeprice" = "TRADEPRICE",
"volume" = "VOLUME",
"ddate" = "DATE",
"ttime_s" = "TIME_S",
"obplotno" = "OBPLOTNO",
"att" = "ATT",
"val" = "VAL",
"sharebal" = "SHAREBAL") %>%
select(-BPROFIT, -SPROFIT, -OBPMINTPRICE, -OBPMAXTPRICE)
# options(digits.secs = 3)
order_atts_cumsums_enh4_df %>%
write_csv("../order-book-plot-find/cum_errors/resources/for_web_app/order_atts_cumsums_enh4_df.csv",
na = "")
order_atts_cumsums_enh4_df
order_atts_cumsums_enh4_df %>%
filter(obplotno == 48851, att == "STVOL") %>%
select(nno, price, att, tradeprice, sobp, bobp)
LS0tDQp0aXRsZTogInByZXBhcmVfYmFsX3Rlc3RpbmdfZGZzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpgYGB7cn0NCmxpYnJhcnkoc2hpbnkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KYGBge3J9DQpvYnBzX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILUdNS04tMjAwNy0xMC0wOC0wOV9vYnBzLmNzdiIpDQojIG9icHNfZGYgPC0gcmVhZF9jc3YoIi4uL29yZGVyLWJvb2stcGxvdC1maW5kL2N1bV9lcnJvcnMvcmVzb3VyY2VzL2Zvcl93ZWJfYXBwL0xLT0gtMjAwNy0xMC0wOF9vYnBzLmNzdiIpDQojIG9icHNfZGYgPC0gcmVhZF9jc3YoIi4uL29yZGVyLWJvb2stcGxvdC1maW5kL2N1bV9lcnJvcnMvcmVzb3VyY2VzL2Zvcl93ZWJfYXBwL3MxX3MyXzIwMDdfb2Jwcy5jc3YiKQ0Kb2Jwc19kZiA8LSBvYnBzX2RmICU+JSANCiAgbXV0YXRlKFRJTUVfUyA9IFRJTUUvMTAwMCkNCm9icHNfZGYNCmBgYA0KDQoNCmBgYHtyfQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILUdNS04tMjAwNy0xMC0wOC0wOV9vcmRlcl9hdHRzX2N1bXN1bXMuY3N2IikNCiMgb3JkZXJfYXR0c19jdW1zdW1zX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILTIwMDctMTAtMDhfb3JkZXJfYXR0c19jdW1zdW1zLmNzdiIpDQojIG9yZGVyX2F0dHNfY3Vtc3Vtc19kZiA8LSByZWFkX2NzdigiLi4vb3JkZXItYm9vay1wbG90LWZpbmQvY3VtX2Vycm9ycy9yZXNvdXJjZXMvZm9yX3dlYl9hcHAvczFfczJfMjAwN19vcmRlcl9hdHRzX2N1bXN1bXMuY3N2IikNCm9yZGVyX2F0dHNfY3Vtc3Vtc19kZg0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2N1bV9hdHRzX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILUdNS04tMjAwNy0xMC0wOC0wOV9vYnBfY3VtX2F0dHMuY3N2IikNCiMgb2JwX2N1bV9hdHRzX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILTIwMDctMTAtMDhfb2JwX2N1bV9hdHRzLmNzdiIpDQojIG9icF9jdW1fYXR0c19kZiA8LSByZWFkX2NzdigiLi4vb3JkZXItYm9vay1wbG90LWZpbmQvY3VtX2Vycm9ycy9yZXNvdXJjZXMvZm9yX3dlYl9hcHAvczFfczJfMjAwN19vYnBfY3VtX2F0dHMuY3N2IikNCm9icF9jdW1fYXR0c19kZg0KYGBgDQoNCmBgYHtyfQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmIDwtIGxlZnRfam9pbihvcmRlcl9hdHRzX2N1bXN1bXNfZGYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnBzX2RmICU+JSBzZWxlY3QoLU9CUExPVE5PLCAtU0VDQ09ERSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIk5PIiwgIkRBVEUiKSkgJT4lIA0KICBzZWxlY3QoTk8sIFNFQ0NPREUsIERBVEVUSU1FTUxMUywgUFJJQ0UsIFRSQURFUFJJQ0UsIFZPTFVNRSwgDQogICAgICAgICBEQVRFLCBUSU1FX1MsIE9CUExPVE5PLCBBVFQsIFZBTCwgDQogICAgICAgICBTSEFSRUJBTCwgQlBST0ZJVCwgU1BST0ZJVCwgT0JQTUlOVFBSSUNFLCBPQlBNQVhUUFJJQ0UsDQogICAgICAgICBDQk9WT0x0ZGNzLCBDU09WT0x0ZGNzLCBCT1ZPTHRkY3MsIFNPVk9MdGRjcywgQlRWT0x0ZGNzLCBTVFZPTHRkY3MsIA0KICAgICAgICAgQ0JPVk9Mb2JwY3MsIENTT1ZPTG9icGNzLCBCT1ZPTG9icGNzLCBTT1ZPTG9icGNzLCBCVFZPTG9icGNzLCBTVFZPTG9icGNzLA0KICAgICAgICAgc29icCwgYm9icCwgbWF4X3NvYnBfYm9icCwgbWludXNfbWF4X3NvYnBfYm9icCwgc3RkYXksIGJ0ZGF5LCBtYXhfc3RkX2J0ZCwNCiAgICAgICAgIG1pbnVzX21heF9zdGRfYnRkKQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmDQpgYGANCg0KYGBge3J9DQpvYnBfbWlubWF4X3RyYWRlcHJpY2UgPC0gZnVuY3Rpb24oYXR0LCB0cmFkZXByaWNlLCBtaW5tYXgpIHsNCiAgYXRfZGYgPC0gdGliYmxlKGF0dCA9IGF0dCwNCiAgICAgICAgICAgICAgICAgIHRyYWRlcHJpY2UgPSB0cmFkZXByaWNlKQ0KICBpZiAobGVuZ3RoKGF0X2RmICU+JQ0KICAgICAgICAgICAgZmlsdGVyKGF0dCA9PSAiQlRWT0wiIHwgYXR0ID09ICJTVFZPTCIpICU+JQ0KICAgICAgICAgICAgLiR0cmFkZXByaWNlKSkgew0KICAgIGlmIChtaW5tYXggPT0gIm1pbiIpIHsNCiAgICAgIG1pbihhdF9kZiAlPiUNCiAgICAgICAgICAgIGZpbHRlcihhdHQgPT0gIkJUVk9MIiB8IGF0dCA9PSAiU1RWT0wiKSAlPiUNCiAgICAgICAgICAgIC4kdHJhZGVwcmljZSAlPiUNCiAgICAgICAgICAgIGN1bW1pbigpKQ0KICAgIH0gZWxzZSBpZiAobWlubWF4ID09ICJtYXgiKSB7DQogICAgICBtYXgoYXRfZGYgJT4lDQogICAgICAgICAgICBmaWx0ZXIoYXR0ID09ICJCVFZPTCIgfCBhdHQgPT0gIlNUVk9MIikgJT4lDQogICAgICAgICAgICAuJHRyYWRlcHJpY2UgJT4lDQogICAgICAgICAgICBjdW1tYXgoKSkNCiAgICB9IGVsc2UgcXVpdCgpDQogIH0gZWxzZSB7DQogICAgICBOQQ0KICB9DQp9DQpgYGANCg0KYGBge3J9DQpvYnBfbWlubWF4X2F0dHNfZGYgPC0gb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmICU+JSANCiAgc2VsZWN0KE5PLCBTRUNDT0RFLCBEQVRFLCBPQlBMT1ROTywgQVRULA0KICAgICAgICAgREFURVRJTUVNTExTLCBQUklDRSwgVFJBREVQUklDRSkgJT4lIA0KICBncm91cF9ieShTRUNDT0RFLCBEQVRFLCBPQlBMT1ROTykgJT4lIA0KICBzdW1tYXJpc2UoT0JQQkVHSU4gPSBtaW4oREFURVRJTUVNTExTKSwgT0JQRU5EID0gbWF4KERBVEVUSU1FTUxMUyksIA0KICAgICAgICAgICAgT0JQQkVHSU5OTyA9IG1pbihOTyksIE9CUEVORE5PID0gbWF4KE5PKSwNCiAgICAgICAgICAgIE9CUE1JTlBSSUNFID0gbWluKFBSSUNFKSwgT0JQTUFYUFJJQ0UgPSBtYXgoUFJJQ0UpKQ0Kb2JwX21pbm1heF9hdHRzX2RmDQpgYGANCg0KYGBge3J9DQpvYnBfY3VtX21pbm1heF9hdHRzX2RmIDwtIGxlZnRfam9pbihvYnBfY3VtX2F0dHNfZGYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JwX21pbm1heF9hdHRzX2RmICU+JSBzZWxlY3QoU0VDQ09ERSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERBVEUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBMT1ROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUEJFR0lOLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQQkVHSU5OTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUEVORE5PLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQRU5ELA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQTUlOUFJJQ0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBNQVhQUklDRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIlNFQ0NPREUiLCAiREFURSIsICJPQlBMT1ROTyIpKSAlPiUgDQogIHNlbGVjdChTRUNDT0RFLCBEQVRFLCBPQlBMT1ROTywgVFJBREVWT0wsIEJVWVNFTExPQlAsDQogICAgICAgICBPQlBCRUdJTiwgT0JQRU5ELCBPQlBCRUdJTk5PLCBPQlBFTkROTywgT0JQTUlOUFJJQ0UsIE9CUE1BWFBSSUNFLA0KICAgICAgICAgVFJBREVTTk9UUkFERVMpICMsIEJVWVNFTExZSUVMRCwgT0JQVERWT0xSQVRJTywgTUlOTUFYUkFUSU8pDQpvYnBfY3VtX21pbm1heF9hdHRzX2RmDQpgYGANCg0KYGBge3J9DQoNCmBgYA0KDQpgYGB7cn0NCm9icF9jdW1fYXR0c19lbmhfZGYgPC0gaW5uZXJfam9pbihvYnBfY3VtX21pbm1heF9hdHRzX2RmLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyX2F0dHNfY3Vtc3Vtc19lbmhhbmNlZF9kZiAlPiUgc2VsZWN0KFNFQ0NPREUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgREFURSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBMT1ROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCUFJPRklULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNQUk9GSVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiU0VDQ09ERSIsICJEQVRFIiwgIk9CUExPVE5PIikpICU+JSANCiAgc2VsZWN0KFNFQ0NPREUsIERBVEUsIE9CUExPVE5PLCBUUkFERVZPTCwgQlVZU0VMTE9CUCwNCiAgICAgICAgIEJQUk9GSVQsIFNQUk9GSVQsDQogICAgICAgICBPQlBCRUdJTiwgT0JQRU5ELCBPQlBCRUdJTk5PLCBPQlBFTkROTywgT0JQTUlOUFJJQ0UsIE9CUE1BWFBSSUNFLA0KICAgICAgICAgVFJBREVTTk9UUkFERVMpICU+JSAjLCBCVVlTRUxMWUlFTEQsIE9CUFREVk9MUkFUSU8sIE1JTk1BWFJBVElPKSAlPiUgDQogIHJlbmFtZSgic2VjY29kZSIgPSAiU0VDQ09ERSIsDQogICAgICAgICAiZGRhdGUiID0gIkRBVEUiLA0KICAgICAgICAgIm9icGxvdG5vIiA9ICJPQlBMT1ROTyIsDQogICAgICAgICAidHJhZGV2b2wiID0gIlRSQURFVk9MIiwNCiAgICAgICAgICJidXlzZWxsb2JwIiA9ICJCVVlTRUxMT0JQIiwNCiAgICAgICAgICJicHJvZml0IiA9ICJCUFJPRklUIiwNCiAgICAgICAgICJzcHJvZml0IiA9ICJTUFJPRklUIiwNCiAgICAgICAgICJvYnBiZWdpbiIgPSAiT0JQQkVHSU4iLA0KICAgICAgICAgIm9icGVuZCIgPSAiT0JQRU5EIiwNCiAgICAgICAgICJvYnBiZWdpbm5vIiA9ICJPQlBCRUdJTk5PIiwNCiAgICAgICAgICJvYnBlbmRubyIgPSAiT0JQRU5ETk8iLA0KICAgICAgICAgIm9icG1pbnByaWNlIiA9ICJPQlBNSU5QUklDRSIsDQogICAgICAgICAib2JwbWF4cHJpY2UiID0gIk9CUE1BWFBSSUNFIiwNCiAgICAgICAgICJicHJvZml0IiA9ICJCUFJPRklUIiwNCiAgICAgICAgICJzcHJvZml0IiA9ICJTUFJPRklUIiwNCiAgICAgICAgICJ0cmFkZXNub3RyYWRlcyIgPSAiVFJBREVTTk9UUkFERVMiKSAlPiUgDQogIGRpc3RpbmN0KCkNCiAgICAgICAgICMgImJ1eXNlbGx5aWVsZCIgPSAiQlVZU0VMTFlJRUxEIiwNCiAgICAgICAgICMgIm9icHRkdm9scmF0aW8iID0gIk9CUFREVk9MUkFUSU8iLA0KICAgICAgICAgIyAibWlubWF4cmF0aW8iID0gIk1JTk1BWFJBVElPIikNCm9icF9jdW1fYXR0c19lbmhfZGYNCmBgYA0KDQpgYGB7cn0NCnRkX3ZvbF9zdW1fZGYgPC0gb2JwX2N1bV9hdHRzX2VuaF9kZiAlPiUgDQogIGdyb3VwX2J5KHNlY2NvZGUsIGRkYXRlKSAlPiUgDQogIHN1bW1hcmlzZSh0ZHZvbHN1bSA9IHN1bSh0cmFkZXZvbCkpDQoNCm9icF9jdW1fYXR0c19lbmhfdm9sYXJyYW5nZWRfZGYgPC0gbGVmdF9qb2luKG9icF9jdW1fYXR0c19lbmhfZGYsDQogICAgICAgICAgdGRfdm9sX3N1bV9kZiwNCiAgICAgICAgICBieSA9IGMoInNlY2NvZGUiLCAiZGRhdGUiKSkgJT4lIA0KICBtdXRhdGUob2Jwc2hhcmVpbnRkID0gdHJhZGV2b2wgLyB0ZHZvbHN1bSkgJT4lIA0KICBzZWxlY3QoLXRkdm9sc3VtKSAlPiUgDQogIGFycmFuZ2Uoc2VjY29kZSwgZGRhdGUsIGRlc2Mob2Jwc2hhcmVpbnRkKSkNCg0Kb2JwX2N1bV9hdHRzX2VuaF92b2xhcnJhbmdlZF9kZg0KYGBgDQoNCmBgYHtyfQ0Kb3B0aW9ucyhkaWdpdHMuc2VjcyA9IDMpDQpvYnBfY3VtX2F0dHNfZW5oX3ZvbGFycmFuZ2VkX2RmICU+JQ0KICB3cml0ZV9jc3YoIi4uL29yZGVyLWJvb2stcGxvdC1maW5kL2N1bV9lcnJvcnMvcmVzb3VyY2VzL2Zvcl93ZWJfYXBwL29icF9jdW1fYXR0c19lbmhfZGYuY3N2IiwNCiAgICAgICAgICAgIG5hID0gIiIpDQpgYGANCg0KYGBge3J9DQpvcmRlcl9hdHRzX2N1bXN1bXNfZW5oMl9kZiA8LSBvcmRlcl9hdHRzX2N1bXN1bXNfZW5oYW5jZWRfZGYgJT4lIA0KICBtdXRhdGUocGNvbG9yID0gaWZfZWxzZShBVFQgPT0gIkJPVk9MIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJhcXVhbWFyaW5lIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoQVRUID09ICJTT1ZPTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNvcmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIzAwNDQ4MSIpKSwNCiAgICAgICAgIHBzaGFwZSA9IDRMLA0KICAgICAgICAgcHNpemUgPSAwLjUpDQpvcmRlcl9hdHRzX2N1bXN1bXNfZW5oMl9kZg0KYGBgDQoNCmBgYHtyfQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaDRfZGYgPC0gb3JkZXJfYXR0c19jdW1zdW1zX2VuaDJfZGYgJT4lIA0KICBhcnJhbmdlKFNFQ0NPREUsIERBVEUsIE5PKSAlPiUgDQogIHJlbmFtZSgibm5vIiA9ICJOTyIsDQogICAgICAgICAic2VjY29kZSIgPSAiU0VDQ09ERSIsDQogICAgICAgICAiZGF0ZXRpbWVtbGxzIiA9ICJEQVRFVElNRU1MTFMiLA0KICAgICAgICAgInByaWNlIiA9ICJQUklDRSIsDQogICAgICAgICAidHJhZGVwcmljZSIgPSAiVFJBREVQUklDRSIsDQogICAgICAgICAidm9sdW1lIiA9ICJWT0xVTUUiLA0KICAgICAgICAgImRkYXRlIiA9ICJEQVRFIiwNCiAgICAgICAgICJ0dGltZV9zIiA9ICJUSU1FX1MiLA0KICAgICAgICAgIm9icGxvdG5vIiA9ICJPQlBMT1ROTyIsDQogICAgICAgICAiYXR0IiA9ICJBVFQiLA0KICAgICAgICAgInZhbCIgPSAiVkFMIiwNCiAgICAgICAgICJzaGFyZWJhbCIgPSAiU0hBUkVCQUwiKSAlPiUgDQogIHNlbGVjdCgtQlBST0ZJVCwgLVNQUk9GSVQsIC1PQlBNSU5UUFJJQ0UsIC1PQlBNQVhUUFJJQ0UpDQojIG9wdGlvbnMoZGlnaXRzLnNlY3MgPSAzKQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaDRfZGYgJT4lDQogIHdyaXRlX2NzdigiLi4vb3JkZXItYm9vay1wbG90LWZpbmQvY3VtX2Vycm9ycy9yZXNvdXJjZXMvZm9yX3dlYl9hcHAvb3JkZXJfYXR0c19jdW1zdW1zX2VuaDRfZGYuY3N2IiwNCiAgICAgICAgICAgIG5hID0gIiIpDQpvcmRlcl9hdHRzX2N1bXN1bXNfZW5oNF9kZg0KYGBgDQoNCmBgYHtyfQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaDRfZGYgJT4lIA0KICBmaWx0ZXIob2JwbG90bm8gPT0gNDg4NTEsIGF0dCA9PSAiU1RWT0wiKSAlPiUgDQogIHNlbGVjdChubm8sIHByaWNlLCBhdHQsIHRyYWRlcHJpY2UsIHNvYnAsIGJvYnApDQpgYGANCg0K